/* ================================================================================
//	Crypteviant!
//	Providing tough encrypted P2P Chat
//	Copyright (C) 2010  Martin Pfeifer, Tobias Rausch
//
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ============================================================================== */

#ifndef ENTROPYPOOLDATA_HPP
#define ENTROPYPOOLDATA_HPP

#include <QtCore/QString>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
#include <QtCore/QWaitCondition>

#include "sha512.hpp"


namespace RandomPool {

    /**
     * @brief Encapsulating access to the internal hash
     * @details This class is thread-safe and all operations are Mutex-protected.\n
     * Internally SHA512 is used to hash the given data twice.\n
     * The size() method returns the amount of characters which have been added to the hash.
     *
     * @class EntropyPoolData entropypooldata.hpp "entropypooldata.hpp"
    */
    class EntropyPoolData
    {
    public:
        /**
         * @brief Default Constructor
         *
         * @fn EntropyPoolData()
        */
        explicit EntropyPoolData();

        /**
         * @brief Add new data to the hash
         * @details The length of given data should be a multiple of @ref EntropyPoolData::optimalBlockSize()
         *
         * @fn addData(const QString)
         * @param data
        */
        void addData(const QString data);

        /**
         * @brief Size of the data which has been hashed
         * @details The size represents the length of data which has already been hashed to the internal hash.
         *
         * @fn size()
         * @return int
        */
        int size();

        /**
         * @brief Get the hashed data
         * @details This will return the hash of the data.\n
         * Currently two iterations of SHA512 will be performed on the data.
         *
         * @fn getData()
         * @return QString
        */
        QString getData();

        /**
         * @brief The optimal size for adding blocks
         * @details If you add data to the hash it is best to have a length which is a multiple of this size.
         *
         * @fn optimalBlockSize() const
         * @return unsigned int
        */
        unsigned int optimalBlockSize() const;

        /**
         * @brief Wait until new data has been added to the hash
         * @details Make sure to check the condition again after you have been woken.\n
         * It may be possible that the amount of data is still not enough for your needs!
         *
         * @fn wait(int)
         * @param time
        */
        void wait(int time = 0);

    private:
        /**
         * @var m_hash
         * @brief Represents the hash as SHA512 which is hashed on-the-fly.\n
        */
        Hash::Sha512 m_hash;

        /**
         * @var m_size
         * @brief The size of tha data which has been hashed
        */
        int m_size;

        /**
         * @var m_mutex
         * @brief Allowing this class to be thread-safe
        */
        QMutex m_mutex;

        /**
         * @var m_waitCond
         * @brief The WaitCondition to wait for enough data.
        */
        QWaitCondition m_waitCond;
    };

} // End of Namespace RandomPool

#endif // ENTROPYPOOLDATA_HPP
